using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using Drawing = System.Drawing;
using Imaging = System.Drawing.Imaging;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content.Pipeline.Graphics;
using Scurvy.Media.Avi;
using Scurvy.Media.VideoModel;
using System.Diagnostics;

namespace Scurvy.Media.Pipeline.Video.Avi
{
    internal sealed class AviVideoContent : IVideoContent
    {
        #region Fields

        private string _filename;
        private AviManager _aviManager;
        private AviVideoStream _stream;
        private int _frameCount;
        private double _frameRate;
        byte[] pixelBuffer;
        private PlaybackType _readType;
        private bool _usecompression;

        #endregion

        public AviVideoContent(string filename)
        {
            _filename = filename;
        }

        #region Properties

        public IEnumerable<Texture2DContent> Frames
        {
            get
            {
                if (_aviManager == null)
                {
                    _aviManager = new AviManager(_filename, true);
                    _stream = _aviManager.GetVideoStream();
                    _stream.GetFrameOpen();
                    _frameCount = _stream.CountFrames;
                    _frameRate = _stream.FrameRate;
                }

                PlatformSurface surface = PlatformSurface.Create();

                for (int i = 0; i < _frameCount; i++)
                {
                    using (Drawing.Bitmap bitmap = GetFrame(surface, i))
                    {
                        Texture2DContent c = TranslateBitmap(bitmap);
                        _size = new Vector2();
                        _size.Y = (float)c.Faces[0][0].Height;
                        _size.X = (float)c.Faces[0][0].Width;
                        yield return c;
                    }
                }
            }
        }

        public bool UseCompression
        {
            get { return _usecompression; }
            set { _usecompression = value; }
        }

        private Drawing.Bitmap GetFrame(PlatformSurface surface, int i)
        {
            //Drawing.Bitmap bmp = _stream.GetBitmap(i, Imaging.PixelFormat.Format16bppRgb565);
            Drawing.Bitmap bmp = _stream.GetBitmap(i, surface.GdiPixelFormat);
            return bmp;
        }

        

        private Texture2DContent TranslateBitmap(System.Drawing.Bitmap bitmap)
        {
            if (this.UseCompression)
            {
                bitmap = ResizeBitmap(bitmap, 64, 64);
            }
            PlatformSurface surface = PlatformSurface.Create();

            Texture2DContent c = new Texture2DContent();
            BitmapContent b = surface.FromGdiBitmap(bitmap);

            c.Faces[0].Add(b);

            //debugging to determine the color byte order on 360
            //Drawing.Graphics g = Drawing.Graphics.FromImage(bitmap);
            //g.Clear(Drawing.Color.Blue);
            //Drawing.Rectangle rect = new System.Drawing.Rectangle(0,0,bitmap.Width, (int)(bitmap.Height/3));
            //g.FillRectangle(new Drawing.SolidBrush(Drawing.Color.Red), rect);
            //rect.Y = (int)(bitmap.Height / 3);
            //g.FillRectangle(new Drawing.SolidBrush(Drawing.Color.Green), rect);
            //rect.Y = (int)(bitmap.Height / 3) * 2;
            //g.FillRectangle(new Drawing.SolidBrush(Drawing.Color.Blue), rect);

            //System.Diagnostics.Debugger.Launch();
            GetData(bitmap, surface);
            //throw new Exception();

            if (this.UseCompression)
            {
                b.SetPixelData(pixelBuffer);
            }
            else
            {
                surface.SetData(b, pixelBuffer);
            }

            if (this.UseCompression)
            {
                c.ConvertBitmapType(typeof(Dxt1BitmapContent));
            }
            else
            {
                c.ConvertBitmapType(typeof(PixelBitmapContent<Microsoft.Xna.Framework.Graphics.PackedVector.Bgr565>));
            }

            return c;
        }

        public Drawing.Bitmap ResizeBitmap(Drawing.Bitmap b, int nWidth, int nHeight)
        {
            Drawing.Bitmap result = new Drawing.Bitmap(nWidth, nHeight);
            using (Drawing.Graphics g = Drawing.Graphics.FromImage((Drawing.Image)result))
                g.DrawImage(b, 0, 0, nWidth, nHeight);
            return result;
        }

        private void GetData(Drawing.Bitmap bmp, PlatformSurface surface)
        {
            // Lock the bitmap's bits.
            Drawing.Rectangle rect = new Drawing.Rectangle(0, 0, bmp.Width, bmp.Height);
            Imaging.BitmapData bmpData =
            bmp.LockBits(rect, Imaging.ImageLockMode.ReadOnly,
                         bmp.PixelFormat);

            // Get the address of the first line.
            IntPtr ptr = bmpData.Scan0;

            // Declare an array to hold the bytes of the bitmap.
            int numBytes = bmp.Width * bmp.Height * surface.SurfaceMultiplier;
            if (pixelBuffer == null)
            {
                pixelBuffer = new byte[numBytes];
            }

            // Copy the RGB values into the array.
            Marshal.Copy(ptr, pixelBuffer, 0, numBytes);
            bmp.UnlockBits(bmpData);
        }

        private Vector2 _size;

        public Vector2 Size
        {
            get { return _size; }
        }

        public double FrameRate
        {
            get { return _frameRate; }
        }

        public int FrameCount
        {
            get { return _frameCount; }
        }

        public PlaybackType PlayType
        {
            get { return _readType; }
            set { _readType = value; }
        }

        #endregion

        public void Dispose()
        {
            _aviManager.Close();
        }
    }
}
